gusucode.com > VC++ EMF图片浏览器(可读emf、wmf、emz、wmz、png……等)-源码程序 > VC++ EMF图片浏览器(可读emf、wmf、emz、wmz、png……等)-源码程序/code/Src/Client/SCSharedLib/SCZipFile.cpp

    //Download by http://www.NewXing.com
/*
*	This file is part of the EMFexplorer projet.
*	Copyright (C) 2004 Smith Charles.
*
*	This library is free software; you can redistribute it and/or
*	modify it under the terms of the GNU Lesser General Public
*	License as published by the Free Software Foundation; either
*	version 2.1 of the License, or (at your option) any later version.
*
*   This library is distributed in the hope that it will be useful,
*   but WITHOUT ANY WARRANTY; without even the implied warranty of
*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
*   Lesser General Public License for more details.
*
*   You should have received a copy of the GNU Lesser General Public
*   License along with this library; if not, write to the Free Software
*   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA.
*
*	Extension: for commercial use, apply the Equity Public License, which
*	adds to the normal terms of the GLPL a condition of donation to the author.
*   If you are interested in support for this source code,
*   contact Smith Charles <smith.charles@free.fr> for more information.
*/


#include "stdafx.h"
#include "SCZipFile.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

#define SC_FREAD_BUFLEN		(1024*32)

// Dup: we don't have them in a header
/* gzip flag byte */
#define SC_GZ_ASCII_FLAG   0x01 /* bit 0 set: file probably ascii text */
#define SC_GZ_HEAD_CRC     0x02 /* bit 1 set: header CRC present */
#define SC_GZ_EXTRA_FIELD  0x04 /* bit 2 set: extra field present */
#define SC_GZ_ORIG_NAME    0x08 /* bit 3 set: original file name present */
#define SC_GZ_COMMENT      0x10 /* bit 4 set: file comment present */
#define SC_GZ_RESERVED     0xE0 /* bits 5..7: reserved */

///////////////////////////////////////////////////////////////////////
// Static
//
inline gzFile SCOpenGZFile(LPCTSTR lpszFName)
{
#ifdef _UNICODE
	char	szAnsiPath[MAX_PATH];
	WideCharToMultiByte(CP_ACP, 0, lpszFName, MAX_PATH, szAnsiPath, MAX_PATH, NULL, NULL);
    gzFile	in = gzopen(szAnsiPath, "rb");
#else
    gzFile	in = gzopen(lpszFName, "rb");
#endif
	return in;
}


///
/// Would like to use an already opened handle to check if file is GZ
///
BOOL SCIsGZFile(HANDLE hFile)
{
	ASSERT(hFile);

	BOOL bYes = FALSE;

	long dwFilePosHigh=0;
	DWORD dwFilePos = SetFilePointer(hFile, 0L, &dwFilePosHigh, FILE_CURRENT);
	if (dwFilePos == 0xFFFFFFFF && (GetLastError() != NO_ERROR))
		return FALSE;
	SetFilePointer(hFile, 0L, NULL, FILE_BEGIN);

	BYTE gzheader[SC_GZHEADER_MINSIZE];
	DWORD dwRead;
	BOOL bResult = ReadFile(hFile, gzheader, SC_GZHEADER_MINSIZE, &dwRead, NULL);
	if (bResult && (SC_GZHEADER_MINSIZE==dwRead))
	{
		// Check the gzip magic header, and method
		if (gzheader[0] == 0x1f	&&
			gzheader[1] == 0x8b	&&
			gzheader[2] == Z_DEFLATED &&
			(gzheader[3] & SC_GZ_RESERVED) == 0)
		{
			// TODO: Now check the header
			bYes = TRUE;
		}
	}

	SetFilePointer(hFile, dwFilePos, &dwFilePosHigh, FILE_BEGIN);
	return bYes;
}

///
/// Check file is GZ
///
BOOL SCIsGZFile(LPCTSTR lpszFName)
{
	ASSERT(lpszFName);

	// Open the file for reading. 
	UINT uiMode = SetErrorMode(SEM_FAILCRITICALERRORS);
    HANDLE hFile = CreateFile(lpszFName, GENERIC_READ, FILE_SHARE_READ, NULL,  
                        OPEN_EXISTING, 0, 0); 
    if (hFile == INVALID_HANDLE_VALUE)
	{
		SetErrorMode(uiMode);
		return FALSE;
	}

	BOOL bYes = SCIsGZFile(hFile);

	CloseHandle(hFile);
	SetErrorMode(uiMode);
	return bYes;
}

///
/// Check if buffer contains "would be GZ" data
///
BOOL SCIsGZCandidate(LPBYTE lpBuff, DWORD dwSize, BOOL bFullCheck/*=FALSE*/)
{
	ASSERT(lpBuff);

	if (dwSize>=SC_GZHEADER_MINSIZE)
	{
		BYTE flags;
		// Check the gzip magic header, and method
		if (lpBuff[0] == 0x1f	&&
			lpBuff[1] == 0x8b	&&
			lpBuff[2] == Z_DEFLATED &&
			((flags=lpBuff[3]) & SC_GZ_RESERVED) == 0)
		{
			if (!bFullCheck)
				return TRUE;

			/* Discard time, xflags and OS code */ 
			DWORD dwPos = SC_GZHEADER_MINSIZE; // skip 6 bytes
			
			if ((flags & SC_GZ_EXTRA_FIELD) != 0)
			{ /* skip the extra field */
				if (dwSize<dwPos+2) return FALSE;

				DWORD dwLen  =  (DWORD)lpBuff[dwPos++];
				dwLen += ((DWORD)lpBuff[dwPos++]) << 8;
				dwPos += dwLen;
				if (dwSize<dwPos) return FALSE;
			}
			if ((flags & SC_GZ_ORIG_NAME) != 0)
			{ /* skip the original file name */
				if (dwSize<dwPos+1) return FALSE;
				for (; dwPos < dwSize && lpBuff[dwPos] != 0; dwPos++)
				{
				}
			}
			if ((flags & SC_GZ_COMMENT) != 0)
			{   /* skip the .gz file comment */
				if (dwSize<dwPos+1) return FALSE;
				for (; dwPos < dwSize && lpBuff[dwPos] != 0; dwPos++)
				{
				}
			}
			if ((flags & SC_GZ_HEAD_CRC) != 0)
			{  /* skip the header crc */
				if (dwSize<dwPos+2) return FALSE;
			}

			return TRUE;
		}
	}
	return FALSE;
}


///
/// Uncompress and write to file
///
BOOL SC_GZUncompress(gzFile in, FILE   *out)
{
    char buf[SC_FREAD_BUFLEN];
    for (;;)
	{
        int len = gzread(in, buf, sizeof(buf));
        if (len < 0)
			 return FALSE;
		
        if (len == 0)
			break;

        if ((int)fwrite(buf, 1, (unsigned)len, out) != len)
            return FALSE;
    }
	return TRUE;
}

///
/// Inflate to the given file
///
BOOL SCUnzipGZFile(LPCTSTR lpszSrcFName, LPCTSTR lpszDestName)
{
	ASSERT(lpszSrcFName);
	ASSERT(lpszDestName);

	gzFile	in = SCOpenGZFile(lpszSrcFName);
	if (!in)
		return FALSE;

#ifdef _UNICODE
    FILE  *out = _wfopen(lpszDestName, L"wb");
#else
    FILE  *out = fopen(lpszDestName, "wb");
#endif
	BOOL bOk = FALSE;
    if (out)
	{
		bOk = SC_GZUncompress(in, out);
		int iRes = fclose(out);
		if (bOk)
			bOk = (0==iRes);
	}

	gzclose(in);
	return bOk;
}

///
/// Inflate directly in memory
///
BOOL SCUnzipGZFile(LPCTSTR lpszSrcFName, CMemFile& rMemFile)
{
	ASSERT(lpszSrcFName);
	
    gzFile	in = SCOpenGZFile(lpszSrcFName);
	if (!in)
		return FALSE;
	
	char buf[SC_FREAD_BUFLEN];
	BOOL bOk = FALSE;
	for (;;)
	{
        int len = gzread(in, buf, sizeof(buf));
        if (len < 0)
			break; // error
		
        if (0 == len)
		{
			bOk = TRUE;
			break;
		}
		
		rMemFile.Write(buf, len);
    }
	
	gzclose(in);
	return bOk;
}

///
/// Partial Inflate in memory
///
BOOL SCUnzipGZFilePart(LPCTSTR lpszSrcFName, LPBYTE pBuff, DWORD dwQuant)
{
	ASSERT(lpszSrcFName);
	ASSERT(pBuff && dwQuant);
	
    gzFile	in = SCOpenGZFile(lpszSrcFName);
	if (!in)
		return FALSE;
	
	BOOL bOk = FALSE;
	int len = gzread(in, (char*)pBuff, dwQuant);
	if (len>=0)
	{
		bOk = TRUE;
	}

	gzclose(in);
	return bOk;
}

///////////////////////////////////////////////////////////////////////
// class CSCMemZip
//

CSCMemZip::CSCMemZip():
	m_nRet(Z_STREAM_END),
	m_dwHeaderSize(0)
{
	memset(&m_zstrm, 0, sizeof(m_zstrm));
}

CSCMemZip::~CSCMemZip()
{
}

BOOL CSCMemZip::SCBeginUnzip(LPBYTE lpszSrcMem, long lSrcSize)
{
	memset(&m_zstrm, 0, sizeof(m_zstrm));
	m_zstrm.next_in = (unsigned char *)lpszSrcMem;
	m_zstrm.avail_in = lSrcSize;
	if ((m_nRet = inflateInit2(&m_zstrm, 15+32)) == Z_OK)
	{// skip header
		unsigned char buf[SC_FREAD_BUFLEN];
		m_zstrm.next_out = buf;
		m_zstrm.avail_out = SC_FREAD_BUFLEN;
		m_nRet = inflate(&m_zstrm, Z_BLOCK);

		if (Z_OK==m_nRet)
			m_dwHeaderSize = m_zstrm.total_in;
	}
	return (m_nRet == Z_OK);
}

BOOL CSCMemZip::SCEndUnzip()
{
	BOOL bOk = (inflateEnd(&m_zstrm) == Z_OK);
	if (m_nRet!=Z_STREAM_END) // SCEndUnzip called prematurely
		bOk = FALSE;
	return bOk;
}

BOOL CSCMemZip::SCUnzipChunk(LPBYTE lpszSrcMem, long lSrcSize)
{
    unsigned char buf[SC_FREAD_BUFLEN];
	long lRemain = lSrcSize;

	m_zstrm.next_in = (unsigned char *)lpszSrcMem;
	m_zstrm.avail_in = lSrcSize;
	
	do
	{
		long lOldRemain = m_zstrm.total_in;
		m_zstrm.next_out = buf;
		m_zstrm.avail_out = SC_FREAD_BUFLEN;

		m_nRet = inflate(&m_zstrm, Z_NO_FLUSH);

		TRACE3("m_nRet=%d total_in=%d m_zstrm.avail_out=%d\n", m_nRet, m_zstrm.total_in, m_zstrm.avail_out);
		long lDone = (m_zstrm.total_in - lOldRemain);
		if (lDone>0)
		{
			lRemain -= lDone;
			m_MemFile.Write(buf, SC_FREAD_BUFLEN - m_zstrm.avail_out);
		} else
			break; // error
	} while (m_nRet==Z_OK && lRemain>0);
	
	return (m_nRet==Z_OK || m_nRet==Z_STREAM_END);
}